package com.jeffpalm.pandoralastfm;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import com.jeffpalm.pandoralastfm.PandoraLastFmBridge.BridgeResult;

public class PandoraLastFm extends App {

  public static void main(String[] args) {
    new PandoraLastFm().realMain(args);
  }

  private Thread updater;
  private boolean going = false;

  private JLabel trackLabel;
  private JLabel artistLabel;
  private JLabel albumLabel;
  private JLabel msgLabel;

  public PandoraLastFm() {
    System.setProperty("com.apple.mrj.application.apple.menu.about.name", "PandoraLastFm");
    System.setProperty("apple.laf.useScreenMenuBar", "true");
    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (ClassNotFoundException _) {} catch (InstantiationException _) {} catch (IllegalAccessException _) {} catch (UnsupportedLookAndFeelException _) {}
  }

  private final class ButtonAction extends JButton {

    private static final long serialVersionUID = 1L;

    ButtonAction(String icon, final String action, final Runnable runner) {
      this(icon, new Runnable() {
        public void run() {
          runner.run();
          showMessage(action);
        }
      });
    }

    ButtonAction(String icon, final Runnable r) {
      super(icon(icon));
      addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
          r.run();
        }
      });
    }
  }

  static ImageIcon icon(String icon) {
    Class<PandoraLastFm> cls = PandoraLastFm.class;
    return new ImageIcon(cls.getResource(icon));
  }

  public void realMain(String[] args) {

    // First try to open PandoraBoy
    try {
      Runtime.getRuntime().exec("open", new String[] { "/Applications/PandoraBoy.app/" });
    } catch (IOException e) {
      handle(e, "Couldn't start PandoraBoy");
    }

    // Set up the frame
    JFrame f = new JFrame(getClass().getName());
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.getContentPane().setLayout(new BoxLayout(f.getContentPane(), BoxLayout.Y_AXIS));

    // Menu bar
    f.setJMenuBar(createMenuBar());

    // Top Panel
    JPanel top = xPanel(f);

    // Set up all the actions
    ButtonAction[] actions = { new ButtonAction("Down24.gif", new Runnable() {
      public void run() {
        pandora().thumbsDown();
      }
    }), new ButtonAction("Up24.gif", new Runnable() {
      public void run() {
        showMessage("thumbs up");
        BridgeResult r = getBridge().up();
        if (!r.isSuccessful()) {
          showError(r.getErrorMessage());
        } else {
          showMessage(r.getSuccessMessage());
        }
      }
    }), new ButtonAction("Pause24.gif", new Runnable() {
      public void run() {
        pandora().pausePlay();
      }
    }), new ButtonAction("Play24.gif", new Runnable() {
      public void run() {
        pandora().pausePlay();
      }
    }), new ButtonAction("FastForward24.gif", new Runnable() {
      public void run() {
        pandora().nextTrack();
        showMessage("next track");
        updateLabels();
      }
    }), };
    for (ButtonAction action : actions)
      top.add(action);

    // Bottom panel
    JPanel bottom = yPanel(f);
    trackLabel = leftPanel(bottom);
    artistLabel = leftPanel(bottom);
    albumLabel = leftPanel(bottom);
    msgLabel = leftPanel(bottom);
    JPanel prefPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
    prefPanel.add(new JButton(new AbstractAction("Preferences") {

      private static final long serialVersionUID = 1L;

      public void actionPerformed(ActionEvent e) {
        showPreferences();
      }
    }));
    prefPanel.add(new JButton(new AbstractAction("Quit") {

      private static final long serialVersionUID = 1L;

      public void actionPerformed(ActionEvent e) {
        System.exit(0);
      }
    }));
    bottom.add(prefPanel);

    going = true;
    updater = new Thread(new Runnable() {
      public void run() {
        while (going) {
          updateLabels();
          try {
            Thread.sleep(5 * 1000);
          } catch (InterruptedException _) {}
        }
      }
    });
    updater.start();

    // Show the frame
    f.pack();
    f.setVisible(true);

    // For quitting
    Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
      public void run() {
        going = false;
        if (updater != null) {
          try {
            updater.join();
          } catch (InterruptedException _) {}
        }
      }
    }));
  }

  private JMenuBar createMenuBar() {
    JMenuBar res = new JMenuBar();
    JMenu file = new JMenu("File");
    res.add(file);
    file.add(new JMenuItem(new AbstractAction("Preferences") {

      private static final long serialVersionUID = 1L;

      public void actionPerformed(ActionEvent e) {
        showPreferences();
      }
    }));
    file.add(new JMenuItem(new AbstractAction("Quit") {

      private static final long serialVersionUID = 1L;

      public void actionPerformed(ActionEvent e) {
        System.exit(0);
      }
    }));
    return res;
  }

  private void showMessage(String msg) {
    showMessage(Color.green.darker(), msg);
  }

  private void showError(String msg) {
    showMessage(Color.red.darker(), msg);
  }

  private void showMessage(final Color c, final String msg) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        msgLabel.setForeground(c);
        msgLabel.setText(msg);
        try {
          Thread.sleep(5000);
        } catch (Exception _) {}
        showMessage(Color.black, "Ready");
        updateLabels();
      }
    });
  }

  private void updateLabels() {
    trackLabel.setText(pandora().getCurrentTrack());
    artistLabel.setText(pandora().getCurrentArtist());
    albumLabel.setText(pandora().getCurrentAlbum());
  }

  private JLabel leftPanel(JPanel into) {
    JPanel p = new JPanel(new FlowLayout(FlowLayout.LEFT));
    JLabel res = new JLabel("...");
    p.add(res);
    into.add(p);
    return res;
  }

  private JPanel xPanel(JFrame f) {
    return panel(f, BoxLayout.X_AXIS);
  }

  private JPanel yPanel(JFrame f) {
    return panel(f, BoxLayout.Y_AXIS);
  }

  private JPanel panel(JFrame f, int align) {
    JPanel p = new JPanel();
    p.setLayout(new BoxLayout(p, align));
    if (f != null) f.getContentPane().add(p);
    return p;
  }

  // --------------------------------------------------
  // Preferences
  // --------------------------------------------------

  private JFrame prefsFrame;
  private PrefsDialog prefsDialog;

  private class PrefsDialog extends JPanel {

    private static final long serialVersionUID = 1L;

    private final JTextField username = new JTextField(getProperty(PROP_USERNAME), 30);
    private final JCheckBox useLastFm = new JCheckBox("Use last.fm");

    PrefsDialog(final JFrame f) {

      setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

      f.getContentPane().setLayout(new BorderLayout());

      JPanel mid = new JPanel();
      mid.setLayout(new BoxLayout(mid, BoxLayout.Y_AXIS));
      add(mid, BorderLayout.CENTER);

      JPanel p = new JPanel();
      mid.add(p);
      p.setBorder(BorderFactory.createTitledBorder("Last.fm username"));
      p.add(username);

      useLastFm.setSelected(getBooleanProperty(PROP_USE_LAST_FM));
      mid.add(useLastFm);

      JPanel bottom = new JPanel(new FlowLayout(FlowLayout.RIGHT));
      add(bottom, BorderLayout.SOUTH);
      bottom.add(new JButton(new AbstractAction("OK") {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
          save(username.getText(), useLastFm.isSelected());
          f.dispose();
          f.setVisible(false);
        }
      }));
      bottom.add(new JButton(new AbstractAction("Cancel") {

        private static final long serialVersionUID = 1L;

        public void actionPerformed(ActionEvent e) {
          f.dispose();
          f.setVisible(false);
        }
      }));
      add(bottom, BorderLayout.SOUTH);
    }

  }

  private void showPreferences() {

    if (prefsFrame != null && prefsFrame.isVisible()) return;

    // Create and set up the window.
    JFrame frame = new JFrame("Preferences");
    prefsFrame = frame;

    // Create and set up the content pane.
    prefsDialog = new PrefsDialog(frame);
    frame.getContentPane().add(prefsDialog);

    // Display the window.
    frame.pack();
    frame.setVisible(true);
  }
}